#include "spi_config.h"
//#include "gd32f4xx_gpio.h"
//#include "gd32f4xx_spi.h"
//#include "gd32f4xx_dma.h"
#include "string.h"
#include "stdio.h"


#define CIRCLE_TEST       1
#define arraysize         10*1024
#define BUFF_SIZE         256*1024 

#define DATA_BUFF_SIZE    16*1024


#if CIRCLE_TEST
#define SEND_DATA_SIZE  1024
#else
#define SEND_DATA_SIZE  15842
#endif

uint8_t spi4_send_array[SEND_DATA_SIZE];
// uint8_t spi3_send_array1[arraysize];
// uint8_t spi4_receive_array[arraysize];
// uint8_t spi3_receive_array0[arraysize];
// uint8_t spi3_receive_array1[arraysize];

uint8_t spi_receive_array0[arraysize];
uint8_t spi_receive_array1[arraysize];

uint8_t sbuff[BUFF_SIZE];
RING_BUF_DEF_STRUCT s_ring_buf_receive; 

uint8_t sdata_buff[DATA_BUFF_SIZE];
RING_BUF_DEF_STRUCT s_ring_buf_data;

static struct{
    uint16_t read_index;
    uint16_t trans_len;
}s_spi_trans_loaction;


////////////////////////////////////////////////
//#include "mk_hal_system.h"

uint32_t receive_correct_count;
uint32_t receive_error_count;


void spi_manage_init(void)
{
    //rcu_periph_clock_enable(RCU_GPIOD);
    //rcu_periph_clock_enable(RCU_GPIOE);
    ////rcu_periph_clock_enable(RCU_GPIOF);
    ////rcu_periph_clock_enable(RCU_DMA0);
    //rcu_periph_clock_enable(RCU_DMA1);
    //rcu_periph_clock_enable(RCU_SPI4);
    ////rcu_periph_clock_enable(RCU_SPI3);

    spi_buff_init();
	//gpio_config();
	//dma_config();
	//spi_config();
	//// spi_dma_enable(SPI3, SPI_DMA_RECEIVE);
 //   // dma_channel_enable(DMA1, DMA_CH3);  
 //   spi_dma_enable(SPI4, SPI_DMA_RECEIVE);
 //   dma_channel_enable(DMA1, DMA_CH3);  
}




void data_init(void)
{
  //  uint16_t i = 0;
  //  for(;i<SEND_DATA_SIZE;i++)
  //  {
  //      spi4_send_array[i] = rand()%256;//i;
  //  }

  //  SET_SPI4_NSS_LOW
  //  //spi_dma_enable(SPI3, SPI_DMA_TRANSMIT);
  //  //spi_dma_enable(SPI3, SPI_DMA_RECEIVE);
  //  spi_dma_enable(SPI4, SPI_DMA_TRANSMIT);
  //  //spi_dma_enable(SPI4, SPI_DMA_RECEIVE);

  //   //dma_channel_enable(DMA1, DMA_CH4);
  //  dma_channel_enable(DMA1, DMA_CH3);
		///* spi4 */
  //  //dma_channel_enable(DMA1, DMA_CH5);
  //  dma_channel_enable(DMA1, DMA_CH6);
  //  //SET_SPI4_NSS_HIGH
}

void data_check(void)
{
    static uint32_t index = 0;
    uint8_t rData[1024];
    uint32_t len = 0;
    uint16_t count = 1024;
    len = RingBuf_Read(&s_ring_buf_receive,count,rData);
    for(uint32_t i=0;i<len;i++)
    {
        if(rData[i] == spi4_send_array[index++%SEND_DATA_SIZE])
            receive_correct_count++;
        else
            receive_error_count++;
    }
    index = 0;
    
}

void result_print(void)
{
 /*   static uint32_t lastTick = 0;

    if(mk_hal_system_get_tick() - lastTick > 1000)
    {
        lastTick = mk_hal_system_get_tick();

        printf("correct = %d,error = %d\n",receive_correct_count,receive_error_count);
        receive_correct_count = 0;
        receive_error_count = 0;

        #if !CIRCLE_TEST
         dma_channel_disable(DMA1, DMA_CH6);
         SET_SPI4_NSS_LOW
         dma_transfer_number_config(DMA1, DMA_CH6,SEND_DATA_SIZE);
         dma_memory_address_config(DMA1, DMA_CH6,DMA_MEMORY_0,(uint32_t)spi4_send_array);
         dma_channel_enable(DMA1, DMA_CH6);
        #endif
    }*/
}


///////////////////////////////////////////////



void spi_buff_init(void)
{
    RingBuf_Init(&s_ring_buf_receive,sbuff,BUFF_SIZE);
    RingBuf_Init(&s_ring_buf_data,sdata_buff,DATA_BUFF_SIZE);
}

RING_BUF_DEF_STRUCT *get_spi_receive_buf(void)
{
    return &s_ring_buf_receive;
}

RING_BUF_DEF_STRUCT *get_data_buf(void)
{
    return &s_ring_buf_data;
}

/*!
    \brief      configure the GPIO peripheral
    \param[in]  none
    \param[out] none
    \retval     none
*/
void gpio_config(void)
{
    // /* configure SPI4 GPIO */
    // gpio_af_set(GPIOF, GPIO_AF_5, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9);
    // gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9);
    // gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9);

    // /* set SPI4_NSS as GPIO*/
    // gpio_mode_set(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_5);
    // gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);

    // /* configure SPI3 GPIO */
    // gpio_af_set(GPIOE, GPIO_AF_5, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
    // gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
    // gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);

    ///* configure SPI4 GPIO */
    //gpio_af_set(GPIOE, GPIO_AF_6, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
    //gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
    //gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);

    //gpio_mode_set(GPIOD,GPIO_MODE_INPUT,GPIO_PUPD_NONE,GPIO_PIN_15);
    //nvic_irq_enable(EXTI10_15_IRQn, 0U, 2U);
    ///* connect key EXTI line to key GPIO pin */
    //syscfg_exti_line_config(EXTI_SOURCE_GPIOD, EXTI_SOURCE_PIN15);
    ///* configure key EXTI line */
    //exti_init(EXTI_15, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    //exti_interrupt_flag_clear(EXTI_15);
}


void dma_config(void)
{
    // dma_single_data_parameter_struct dma_init_struct;

    // /* configure SPI4 transmit dma */
    // dma_deinit(DMA1, DMA_CH6);
    // dma_init_struct.periph_addr         = (uint32_t)&SPI_DATA(SPI4);
    // dma_init_struct.memory0_addr        = (uint32_t)spi4_send_array;
    // dma_init_struct.direction           = DMA_MEMORY_TO_PERIPH;
    // dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    // dma_init_struct.priority            = DMA_PRIORITY_LOW;
    // dma_init_struct.number              = SEND_DATA_SIZE;
    // dma_init_struct.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
    // dma_init_struct.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
    // #if CIRCLE_TEST
    // dma_init_struct.circular_mode       = DMA_CIRCULAR_MODE_ENABLE;
    // #else
    // dma_init_struct.circular_mode       = DMA_CIRCULAR_MODE_DISABLE;
    // #endif
    // dma_single_data_mode_init(DMA1, DMA_CH6, &dma_init_struct);
    // dma_channel_subperipheral_select(DMA1, DMA_CH6, DMA_SUBPERI7);
    // #if !CIRCLE_TEST
    // dma_interrupt_enable(DMA1,DMA_CH6,DMA_CHXCTL_FTFIE);
    // nvic_irq_enable(DMA1_Channel6_IRQn, 0, 2);
    // #endif

    /* configure SPI4 receive dma */
    // dma_deinit(DMA1, DMA_CH5);
    // dma_init_struct.periph_addr  = (uint32_t)&SPI_DATA(SPI4);
    // dma_init_struct.memory0_addr = (uint32_t)spi4_receive_array;
    // dma_init_struct.direction    = DMA_PERIPH_TO_MEMORY;
    // dma_init_struct.priority     = DMA_PRIORITY_HIGH;
    // dma_single_data_mode_init(DMA1, DMA_CH5, &dma_init_struct);
    // dma_channel_subperipheral_select(DMA1, DMA_CH5, DMA_SUBPERI7);

    /* configure SPI3 transmit dma */
    // dma_deinit(DMA1, DMA_CH4);
    // dma_init_struct.periph_addr  = (uint32_t)&SPI_DATA(SPI3);
    // dma_init_struct.memory0_addr = (uint32_t)spi3_send_array1;
    // dma_init_struct.direction    = DMA_MEMORY_TO_PERIPH;
    // dma_init_struct.priority     = DMA_PRIORITY_MEDIUM;
    // dma_single_data_mode_init(DMA1, DMA_CH4, &dma_init_struct);
    // dma_channel_subperipheral_select(DMA1, DMA_CH4, DMA_SUBPERI5);

    ///* configure SPI4 receive dma */
    //dma_single_data_parameter_struct dma_init_struct;
    //dma_deinit(DMA1, DMA_CH3);
    //dma_init_struct.periph_addr  = (uint32_t)&SPI_DATA(SPI4);
    //dma_init_struct.memory0_addr = (uint32_t)spi_receive_array0;
    //dma_init_struct.direction    = DMA_PERIPH_TO_MEMORY;
    //dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    //dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;
    //dma_init_struct.number              = arraysize;
    //dma_init_struct.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
    //dma_init_struct.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
    //dma_init_struct.circular_mode       = DMA_CIRCULAR_MODE_ENABLE;
    //dma_single_data_mode_init(DMA1, DMA_CH3, &dma_init_struct);
    //dma_channel_subperipheral_select(DMA1, DMA_CH3, DMA_SUBPERI2);
    //dma_switch_buffer_mode_config(DMA1, DMA_CH3, (uint32_t)(&spi_receive_array1), DMA_MEMORY_1);
    //dma_switch_buffer_mode_enable(DMA1, DMA_CH3, ENABLE);
    //dma_interrupt_enable(DMA1,DMA_CH3,DMA_CHXCTL_FTFIE);
    //nvic_irq_enable(DMA1_Channel3_IRQn, 0, 1);
    //dma_flow_controller_config(DMA1,DMA_CH3,DMA_FLOW_CONTROLLER_PERI);

    /* enable DMA channel spi3*/
    // dma_channel_enable(DMA1, DMA_CH4);
    // dma_channel_enable(DMA1, DMA_CH3);
	// 	/* spi4 */
    // dma_channel_enable(DMA1, DMA_CH5);
    // dma_channel_enable(DMA1, DMA_CH6);
}

/*!
    \brief      configure the SPI peripheral
    \param[in]  none
    \param[out] none
    \retval     none
*/
void spi_config(void)
{
    //spi_parameter_struct spi_init_struct;

    ///* configure SPI4 parameter */
    //spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    ////spi_init_struct.device_mode          = SPI_MASTER;
    //spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    //spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
    ////spi_init_struct.nss                  = SPI_NSS_SOFT;
    //spi_init_struct.prescale             = SPI_PSC_4;
    //spi_init_struct.endian               = SPI_ENDIAN_MSB;
    ////spi_init(SPI4, &spi_init_struct);

    ///* configure SPI3 parameter */
    //spi_init_struct.device_mode = SPI_SLAVE;
    //spi_init_struct.nss         = SPI_NSS_HARD;
    //spi_init(SPI4, &spi_init_struct);

    // /* enable SPI */
    //spi_enable(SPI4);
    ////spi_enable(SPI3);
}

void DMA1_Channel3_IRQHandler(void)
{
    //uint8_t* pbuf = NULL;
    //if(dma_interrupt_flag_get(DMA1,DMA_CH3,DMA_INTF_FTFIF) != RESET)
    //{
    //    dma_interrupt_flag_clear(DMA1,DMA_CH3,DMA_INTF_FTFIF);

    //    if(dma_using_memory_get(DMA1,DMA_CH3) == DMA_MEMORY_1)
    //    {
    //        pbuf = spi_receive_array0;
    //    } 
    //    else
    //    {
    //        pbuf = spi_receive_array1;
    //    }
    //   
    //    RingBuf_Write(&s_ring_buf_receive, pbuf+s_spi_trans_loaction.read_index, arraysize-s_spi_trans_loaction.read_index);
    //    s_spi_trans_loaction.trans_len = 0;
    //    s_spi_trans_loaction.read_index = 0;
    //    memset(pbuf,0,1024);
    //}
}


void EXTI10_15_IRQHandler(void)
{
    //uint8_t* pbuf = NULL;
    //if(exti_interrupt_flag_get(EXTI_15) != RESET)
    //{
    //    exti_interrupt_flag_clear(EXTI_15);

    //    if(dma_using_memory_get(DMA1,DMA_CH3) == DMA_MEMORY_1)
    //    {
    //        pbuf = spi_receive_array1;
    //    } 
    //    else
    //    {
    //        pbuf = spi_receive_array0;
    //    }
    //    s_spi_trans_loaction.trans_len = arraysize-dma_transfer_number_get(DMA1,DMA_CH3) - s_spi_trans_loaction.read_index;
    //    RingBuf_Write(&s_ring_buf_receive, pbuf+s_spi_trans_loaction.read_index, s_spi_trans_loaction.trans_len);
    //    s_spi_trans_loaction.read_index += s_spi_trans_loaction.trans_len; 
    //}
}

#if !CIRCLE_TEST
void DMA1_Channel6_IRQHandler(void)
{
    //if(dma_interrupt_flag_get(DMA1,DMA_CH6,DMA_INTF_FTFIF) != RESET)
    //{
    //    dma_interrupt_flag_clear(DMA1,DMA_CH6,DMA_INTF_FTFIF);

    //    SET_SPI4_NSS_HIGH
    //}
}
#endif

